//
//  JXWaveView.m
//  JXWaveAnimationDemo
//
//  Created by raymond on 16/12/6.
//  Copyright © 2016年 raymond. All rights reserved.
//

#import "JXWaveView.h"

typedef NS_ENUM(NSInteger, JXWavePathType) {
    JXWavePathType_Sin,
    JXWavePathType_Cos
};

@interface JXWaveView ()

@property (nonatomic, assign) CGFloat frequency; // 频率
@property (nonatomic, strong) UIImageView *grayImageView;
@property (nonatomic, strong) UIImageView *sinImageView;
@property (nonatomic, strong) UIImageView *cosImageView;
@property (nonatomic, strong) CAShapeLayer *waveSinLayer;
@property (nonatomic, strong) CAShapeLayer *waveCosLayer;
@property (nonatomic, strong) CADisplayLink *displayLink;

//波浪相关的参数
@property (nonatomic, assign) CGFloat waveWidth;
@property (nonatomic, assign) CGFloat waveHeight;
@property (nonatomic, assign) CGFloat waveMid;
@property (nonatomic, assign) CGFloat maxAmplitude;

@property (nonatomic, assign) CGFloat phaseShift;
@property (nonatomic, assign) CGFloat phase;

@end

@implementation JXWaveView

+ (instancetype)loadingView {
    return [[self alloc] initWithFrame:CGRectMake(0, 0, 40, 31)];
}

- (instancetype)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        [self setupSubviews];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super initWithCoder:aDecoder]) {
        [self setupSubviews];
    }
    return self;
}

- (void)setupSubviews {
    [self addSubview:self.grayImageView];
    [self addSubview:self.sinImageView];
    [self addSubview:self.cosImageView];
    self.sinImageView.layer.mask = self.waveSinLayer;
    self.cosImageView.layer.mask = self.waveCosLayer;

    self.waveHeight = CGRectGetHeight(self.bounds) * 0.5;
    self.waveWidth  = CGRectGetWidth(self.bounds);
    self.frequency = .3;
    self.phaseShift = 8;
    self.waveMid = self.waveWidth / 2.0f;
    self.maxAmplitude = self.waveHeight * .3;
}

- (CGSize)intrinsicContentSize {
    return CGSizeMake(40, 31);
}

- (void)startLoading {
    [_displayLink invalidate];
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    CGPoint point = self.waveSinLayer.position;
    point.y = point.y - self.bounds.size.height - 10;
    CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"position"];
    animation.fromValue = [NSValue valueWithCGPoint:self.waveSinLayer.position];
    animation.toValue = [NSValue valueWithCGPoint:point];
    animation.duration = 5;
    animation.repeatCount = HUGE_VALF;
    animation.removedOnCompletion = NO;
    [self.waveSinLayer addAnimation:animation forKey:@"JXWaveAnimation"];
    [self.waveCosLayer addAnimation:animation forKey:@"JXWaveAnimation"];
}

- (void)stopLoading {
    [self.displayLink invalidate];
    [self.waveSinLayer removeAllAnimations];
    [self.waveCosLayer removeAllAnimations];
    self.waveSinLayer.path = nil;
    self.waveCosLayer.path = nil;
}

- (BOOL)isLoading {
    if (self.waveSinLayer.path) {
        return YES;
    } else {
        return NO;
    }
}

- (void)updateWave {
    self.phase += self.phaseShift;
    self.waveSinLayer.path = [self createWavePathWithType:JXWavePathType_Sin].CGPath;
    self.waveCosLayer.path = [self createWavePathWithType:JXWavePathType_Cos].CGPath;
}

- (UIBezierPath *)createWavePathWithType:(JXWavePathType)pathType {
    UIBezierPath *bezierPath = [UIBezierPath bezierPath];
    CGFloat endX = 0;
    for (CGFloat x = 0; x < self.waveWidth + 1; ++x) {
        endX = x;
        CGFloat y = 0;
        if (pathType == JXWavePathType_Sin) {
            y = self.maxAmplitude * sinf(360.0 / _waveWidth * (x * M_PI / 180) * self.frequency + self.phase * M_PI/ 180) + self.maxAmplitude;
        } else {
            y = self.maxAmplitude * cosf(360.0 / _waveWidth * (x * M_PI / 180) * self.frequency + self.phase * M_PI/180) + self.maxAmplitude;
        }
        if (x == 0) {
            [bezierPath moveToPoint:CGPointMake(x, y)];
        } else {
            [bezierPath addLineToPoint:CGPointMake(x, y)];
        }
    }
    CGFloat endY = CGRectGetHeight(self.bounds) + 10;
    [bezierPath addLineToPoint:CGPointMake(endX, endY)];
    [bezierPath addLineToPoint:CGPointMake(0, endY)];
    return bezierPath;
}

#pragma mark - getter

- (UIImageView *)grayImageView {
    if (!_grayImageView) {
        _grayImageView = [[UIImageView alloc] initWithFrame:self.bounds];
        [_grayImageView setImage:[UIImage imageNamed:@"du"]];
    }
    return _grayImageView;
}

- (UIImageView *)sinImageView {
    if (!_sinImageView) {
        _sinImageView = [[UIImageView alloc] initWithFrame:self.bounds];
        [_sinImageView setImage:[UIImage imageNamed:@"blue"]];
    }
    return _sinImageView;
}

- (UIImageView *)cosImageView {
    if (!_cosImageView) {
        _cosImageView = [[UIImageView alloc] initWithFrame:self.bounds];
        [_cosImageView setImage:[UIImage imageNamed:@"gray"]];
    }
    return _cosImageView;
}

- (CAShapeLayer *)waveSinLayer {
    if (!_waveSinLayer) {
        _waveSinLayer = [CAShapeLayer layer];
        _waveSinLayer.backgroundColor = [UIColor clearColor].CGColor;
        _waveSinLayer.fillColor = [UIColor greenColor].CGColor;
        _waveSinLayer.frame = CGRectMake(0, self.bounds.size.height, self.bounds.size.width, self.bounds.size.height);
    }
    return _waveSinLayer;
}

- (CAShapeLayer *)waveCosLayer {
    if (!_waveCosLayer) {
        _waveCosLayer = [CAShapeLayer layer];
        _waveCosLayer.backgroundColor = [UIColor clearColor].CGColor;
        _waveCosLayer.fillColor = [UIColor blueColor].CGColor;
        _waveCosLayer.frame = CGRectMake(0, self.bounds.size.height, self.bounds.size.width, self.bounds.size.height);
    }
    return _waveCosLayer;
}

- (CADisplayLink *)displayLink {
    if (!_displayLink) {
        _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(updateWave)];
    }
    return _displayLink;
}

@end
